// 
// SoapTrace.Net - A soap message monitoring utility. 
// 
// Copyright (C) 2004 Matthew Ward
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Matthew Ward (mrward@users.sourceforge.net)
// 

using SoapTrace.Core.Gui;
using SoapTrace.Core.Diagnostics;
using System;
using System.Net;
using System.Windows.Forms;

namespace SoapTrace.Core.Formatters
{
	/// <summary>
	/// The configuration editor used to configure the SoapMessageFormatter.
	/// </summary>
	public class FormatterConfigurationEditor : IConfigurationEditor, IDisposable
	{
		/// <summary>
		/// Disposed flag.
		/// </summary>
		private bool m_Disposed;
		
		/// <summary>
		/// The config form.
		/// </summary>
		private SoapMessageFormatterConfigForm m_ConfigForm;

		/// <summary>
		/// The formatter configuration.
		/// </summary>
		private SoapMessageFormatterConfig m_Config;

		/// <summary>
		/// The supported parameter types.
		/// </summary>
		private string[ ] SupportedParameterTypes = 
			new string[ ] { "boolean", "int", "int.array", "string", "string.array", "xml", "xml.array" };

		/// <summary>
		/// The supported return value types.
		/// </summary>
		private string[ ] SupportedReturnValueTypes = 
			new string[ ] { "compressedXml", "int", "int.array", "string", "string.array", "xml", "xml.array" };

		/// <summary>
		/// The web services that we have configured.
		/// </summary>
		private WebServiceCollection m_WebServices;

		/// <summary>
		/// The message formatter to be configured.
		/// </summary>
		private SoapMessageFormatter m_Formatter;

		/// <summary>
		/// Creates a new instance of this class.
		/// </summary>
		public FormatterConfigurationEditor( SoapMessageFormatterConfig config,
			SoapMessageFormatter formatter )
		{
			// Create the main config form.

			m_ConfigForm = new SoapMessageFormatterConfigForm( this );

			// Save a reference to the current configuration.

			m_Config = config;

			// Set up supported parameter types.

			m_ConfigForm.AddParameterTypes( SupportedParameterTypes );

			// Set up the supported return value types.

			m_ConfigForm.AddReturnValueTypes( SupportedReturnValueTypes );

			// Add web services to the config form.  Adds a copy 
			// of the web services so we can undo any changes we have made.

			m_WebServices = ( WebServiceCollection )m_Config.WebServices.Clone( );
			m_ConfigForm.AddWebServices( m_WebServices );

			// Save the message formatter.

			m_Formatter = formatter;
		}
		
		/// <summary>
		/// Disposes this class.
		/// </summary>
		public void Dispose()
		{
			Dispose( true );

			GC.SuppressFinalize( this );
		}		

		/// <summary>
		/// The user has selected a web service operation so display its
		/// properties.
		/// </summary>
		/// <param name="operation">The web service operation selected.</param>
		public void WebServiceOperationSelected( WebServiceOperation operation )
		{
			m_ConfigForm.ClearSelectedWebServiceOperation( );

			if( operation != null )
			{
				m_ConfigForm.WebServiceOperationName = operation.Name;
				m_ConfigForm.AddParameters( operation.Parameters );
				m_ConfigForm.AddReturnValue( operation.ReturnValue );
			}
		}

		/// <summary>
		/// The user has selected a parameter.
		/// </summary>
		/// <param name="parameter">The web service's parameter selected.</param>
		public void ParameterSelected( WebServiceParameter parameter )
		{
			m_ConfigForm.ParameterName = parameter.Name;
			m_ConfigForm.ParameterType = parameter.ParameterType;
			m_ConfigForm.DisplayParameter = parameter.Display;
		}

		/// <summary>
		/// The user has selected a return value.
		/// </summary>
		/// <param name="returnValue">The web service return value selected.</param>
		public void ReturnValueSelected( WebServiceReturnValue returnValue )
		{
			m_ConfigForm.ReturnValueName = returnValue.Name;
			m_ConfigForm.ReturnValueType = returnValue.ParameterType;
			m_ConfigForm.DisplayReturnValue = returnValue.Display;
		}

		/// <summary>
		/// The parameter type has changed.
		/// </summary>
		/// <param name="parameter"></param>
		public void ParameterTypeChanged( WebServiceParameter parameter )
		{
			parameter.ParameterType = m_ConfigForm.ParameterType;
		}

		/// <summary>
		/// The return value type has changed.
		/// </summary>
		/// <param name="returnValue"></param>
		public void ReturnValueTypeChanged( WebServiceReturnValue returnValue )
		{
			returnValue.ParameterType = m_ConfigForm.ReturnValueType;
		}

		/// <summary>
		/// The parameter display value has changed.
		/// </summary>
		/// <param name="parameter"></param>
		public void DisplayParameterChanged( WebServiceParameter parameter )
		{
			parameter.Display = m_ConfigForm.DisplayParameter;
		}

		/// <summary>
		/// The return value display property has changed.
		/// </summary>
		/// <param name="returnValue"></param>
		public void DisplayReturnValueChanged( WebServiceReturnValue returnValue )
		{
			returnValue.Display = m_ConfigForm.DisplayReturnValue;
		}

		/// <summary>
		/// Saves changes to the configuration.
		/// </summary>
		public void SaveChanges( )
		{
			m_Config.WebServices.Clear( );
			m_Config.WebServices.AddRange( m_WebServices );
			m_Config.Save( );

			m_Formatter.WebServices.Clear( );
			m_Formatter.WebServices.AddRange( m_WebServices );
		}

		/// <summary>
		/// Undo any changes made to the configuration.
		/// </summary>
		public void UndoChanges( )
		{
			// Reset the web services and clear the config form.

			m_WebServices = ( WebServiceCollection )m_Config.WebServices.Clone( );
			m_ConfigForm.Clear( );
			m_ConfigForm.AddWebServices( m_WebServices );
		}

		/// <summary>
		/// Adds a web service to the formatter configuration.
		/// </summary>
		/// <param name="url">The web service url.</param>
		public void AddWebService( string url )
		{
			try
			{
				WebServicesDescriptionLanguageFile Wsdl = 
					new WebServicesDescriptionLanguageFile( );
				
				Wsdl.LoadFromUrl( url );
				
				m_WebServices.Add( Wsdl.WebService );
				m_ConfigForm.AddWebService( Wsdl.WebService );
				
			}
			catch( WebException Ex )
			{
				Logger.LogError( String.Concat( "Unable to add web service. ", Ex.ToString( ) ) );
				SoapMessageFormatterConfigForm.ShowError( Ex.Message );
			}
		}
		
		#region IConfigurationEditor Members

		/// <summary>
		/// Shows the config editor's dialog.
		/// </summary>
		public void Show( )
		{
			m_ConfigForm.ShowDialog( );
		}

		#endregion
		
		/// <summary>
		/// Disposes managed and unmanaged objects. 
		/// </summary>
		/// <param name="disposing">If <see langword="true"/> the method has been called directly
		/// or indirectly by a user's code. Managed and unmanaged resources
		/// can be disposed.
		/// If disposing equals <see langword="false"/>, the method has been called by the 
		/// runtime from inside the finalizer and you should not reference 
		/// other objects. Only unmanaged resources can be disposed.
		/// </param>
		private void Dispose( bool disposing )
		{
			if( !m_Disposed )
			{
				if( disposing )
				{
					// Dispose managed resources.

					if( m_ConfigForm != null )
					{
						m_ConfigForm.Dispose( );
						m_ConfigForm = null;
					}
				}
	             
				// Clean up unmanaged resources here.
 
			}

			m_Disposed = true;         
		}		
	}
}
